#include "NodeVisitor.h"

ClassDeclarationNode* CheckingVisitor::GetContainingClassFor(ParseNode *n) {
	if (n->Type() == "ClassDeclaration" || n->Type() == "InterfaceDeclaration") return (ClassDeclarationNode*)n;

	ParentNode *p = n->parent;
	for (; p && p->Type() != "ClassDeclaration" && p->Type() != "InterfaceDeclaration"; p = p->parent);
	return (ClassDeclarationNode*)p;
}

bool CheckingVisitor::CanAccessMember(ModifiedNode *n, ParseNode *context, ClassDeclarationNode *calling_class) {
	if (!(n->access & ModifiedNode::Protected)) return true;

	ClassDeclarationNode *node_class = GetContainingClassFor(n), *context_class = GetContainingClassFor(context);

	//if (node_class->package_name != context_class->package_name) return false;

	bool result = true;

	//The class using this member needs to be a subclass of the one declaring it, or be in the same package
	ClassDeclarationNode *c = context_class;
	for (; c && c != node_class; c = c->super);

	if (!c) {
		result &= node_class->package_name == context_class->package_name;
	}
	
	//The type from which the members being accessed needs to a subclass of the one using it
	c = calling_class;
	for (; c && c != context_class; c = c->super);

	if (!c) {
		result &= context_class->package_name == calling_class->package_name;
	}

	return result;
}

bool CheckingVisitor::CanAccessConstructor(ModifiedNode *constructor, ParseNode *context) {
	if (!(constructor->access & ModifiedNode::Protected)) return true;

	return GetContainingClassFor(constructor)->package_name == GetContainingClassFor(context)->package_name;
}